package com.wdy.dao.impl;

import java.sql.SQLException;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.wdy.dao.TenementDao;
import com.wdy.po.Building;
import com.wdy.po.Tenement;
import com.wdy.util.TypeUtil;
import com.wdy.vo.Condition;
import com.wdy.vo.Page;
@SuppressWarnings("unchecked")
public class TenementDaoHibernateImpl extends HibernateDaoSupport implements TenementDao {
	
	private static final Log log = LogFactory.getLog(TenementDaoHibernateImpl.class);
	private static final String ID = "ID";
	
	//hibernate.lock
	
	public void attachClean(Tenement instance) {
		log.info("attaching clean Tenement instance");
		try {
			getHibernateTemplate().lock(instance, LockMode.NONE);
			log.info("attach successful");
		} catch (DataAccessException e) {
			log.error("attach failed", e);
			throw e;
		}
	}
	//hibernate.saveOrUpdate
	
	public void attachDirty(Tenement instance) {
		log.info("attaching dirty Tenement instance");
		try {
			getHibernateTemplate().saveOrUpdate(instance);
			log.info("attach successful");
		} catch (DataAccessException e) {
			log.error("attach failed", e);
			throw e;
		}
		
	}
	//hibernate.delete
	
	public void delete(Tenement persistentInstance) {
		log.info("deleting Tenement instance");
		try {
			getHibernateTemplate().delete(persistentInstance);
			log.info("delete successful");
		} catch (DataAccessException e) {
			log.error("delete failed", e);
			throw e;
		}
	}
	//hibernate.find
	
	public List<Tenement> findAll() {
		log.info("finding all");
		try {
			String queryString = "from Tenement";
			List<Tenement> result = (List<Tenement>)getHibernateTemplate().find(queryString);
			log.info("find all successful,result size: " + result.size());
			return result;
		} catch (DataAccessException e) {
			log.error("find all failed", e);
			throw e;
		}
	}
	//hibernate.findByExample
	
	public List<Tenement> findByExample(Tenement instance) {
		log.info("finding Tenement instance by example");
		try {
			List<Tenement> result = (List<Tenement>)getHibernateTemplate().findByExample(instance);
			log.info("find Tenement instance by example successful, result size: " + result.size());
			return result;
		} catch (DataAccessException e) {
			log.error("find Tenement instance by example failed", e);
			throw e;
		}
	}
	//hibernate.findById

	public Tenement findById(Integer id) {
		log.info("finding Tenement instance by id");
		try {
			Tenement tenement = (Tenement)getHibernateTemplate().get(Tenement.class, id);
			log.info("find Tenement instance by id successful");
			return tenement;
		} catch (DataAccessException e) {
			log.error("find Tenement instance by id failed", e);
			throw e;
		}
	}
	//hibernate.find
	
	public List<Tenement> findByProperty(String propertyName, Object value) {
		log.info("finding Tenement instance with property: " + propertyName + ", value: " + value);
		String queryString = "from Tenement as model where model." + propertyName + "=?";
		try {
			List<Tenement> result = (List<Tenement>)getHibernateTemplate().find(queryString, value);
			log.info("find Tenement instance by property successful, result size: " + result.size());
			return result;
		} catch (DataAccessException e) {
			log.error("find Tenement instance by property failed", e);
			throw e;
		}
	}
	//findByProperty
	
	public List<Tenement> findByID(String value) {
		return findByProperty(ID, value);
	}
	//findBuildingByTenement
	
	public List<Building> findBuilding(Object value) {
		log.info("finding Building instance by Tenement");
		String queryString = "from Building as model where model.tenement=?";
		try {
			List<Building> result = (List<Building>)getHibernateTemplate().find(queryString, value);
			log.info("find Building instance by Tenement successful, result size: " + result.size());
			return result;
		} catch (DataAccessException e) {
			log.error("find Building instance by Tenement failed", e);
			throw e;
		}
	}
	//hibernate.merge
	
	public Tenement merge(Tenement detachedInstance) {
		log.info("merging Tenement instance");
		try {
			Tenement Tenement = (Tenement)getHibernateTemplate().merge(detachedInstance);
			log.info("merge Tenement successful");
			return Tenement;
		} catch (DataAccessException e) {
			log.error("merge Tenement failed", e);
			throw e;
		}
	}
	//hibernate.save
	
	public void save(Tenement transientInstance) {
		log.info("saving Tenement instance");
		try {
			getHibernateTemplate().save(transientInstance);
			log.info("save Tenement instance successful");
		} catch (DataAccessException e) {
			log.error("save Tenement instance failed", e);
			throw e;
		}
	}
	
	@Override
	public DetachedCriteria getCriteria(List<Condition> conList) {
		// TODO Auto-gene}rated method stub
		DetachedCriteria detachedCriteria = DetachedCriteria
				.forClass(Tenement.class);
		for (Condition con : conList) {
			String propertyName = con.getPropertyName();
			String relation = con.getRelation();
			Object[] tempArray = con.getValues();
			Object[] values = new Object[tempArray.length];
			int[] types = con.getTypes();
			values = TypeUtil.getType(tempArray, types);
			
			if ("eq".equals(relation)) {
				detachedCriteria.add(Restrictions.eq(propertyName, values[0]));
			} else if ("like".equals(relation)) {
				detachedCriteria.add(Restrictions
						.ilike(propertyName, "%" + values[0] +"%"));
			} else if ("in".equals(relation)) {
				detachedCriteria.add(Restrictions.in(propertyName, values));
			} else if ("between".equals(relation)) {
				detachedCriteria.add(Restrictions.between(propertyName,
						values[0], values[1]));
			} else if ("ge".equals(relation)) {
				detachedCriteria.add(Restrictions.ge(propertyName, values[0]));
			} else if ("le".equals(relation)) {
				detachedCriteria.add(Restrictions.le(propertyName, values[0]));
			} else if ("ne".equals(relation)) {
				detachedCriteria.add(Restrictions.ne(propertyName, values[0]));
			}
		}
		return detachedCriteria;
	}

	@Override
	public List query(List<Condition> conList, final Page page) {
		// TODO Auto-generated method stub
		log.info("querying multiple for Tenement instances");
		final DetachedCriteria detachedCriteria = getCriteria(conList);
		List result = (List) getHibernateTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				// TODO Auto-generated method stub
				Criteria criteria = detachedCriteria
						.getExecutableCriteria(session);
				criteria.setFirstResult(page.getBeginIndex());
				criteria.setMaxResults(page.getEveryPage());
				criteria.addOrder(Order.asc("tid"));
				criteria.setProjection(null);
				return criteria.list();
			}
		});
		return result;
	}

	@Override
	public int getQueryCount(List<Condition> conList) {
		// TODO Auto-generated method stub
		final DetachedCriteria detachedCriteria = getCriteria(conList);
		List result = (List) getHibernateTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				// TODO Auto-generated method stub
				Criteria criteria = detachedCriteria
						.getExecutableCriteria(session);
				criteria.setProjection(null);
				return criteria.list();
			}
		});
		return result.size();
	}

	@Override
	public void deleteBatch(final Object[] objects) {
		// TODO Auto-generated method stub
		getHibernateTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				// TODO Auto-generated method stub
				String queryString = "delete from Tenement where tid in (:tid)";
				Query query = session.createQuery(queryString);
				query.setParameterList("tid", objects);
				query.executeUpdate();
				return null;
			}
		});
	}
	
}
